﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TheEnd
{
    /** 
 * 该类提供格式化JSON字符串的方法。 
 * 该类的方法formatJson将JSON字符串格式化，方便查看JSON数据。 
 * <p>例如： 
 * <p>JSON字符串：["yht","xzj","zwy"] 
 * <p>格式化为： 
 * <p>[ 
 * <p>     "yht", 
 * <p>     "xzj", 
 * <p>     "zwy" 
 * <p>] 
 *  
 * <p>使用算法如下： 
 * <p>对输入字符串，追个字符的遍历 
 * <p>1、获取当前字符。 
 * <p>2、如果当前字符是前方括号、前花括号做如下处理： 
 * <p>（1）如果前面还有字符，并且字符为“：”，打印：换行和缩进字符字符串。 
 * <p>（2）打印：当前字符。 
 * <p>（3）前方括号、前花括号，的后面必须换行。打印：换行。 
 * <p>（4）每出现一次前方括号、前花括号；缩进次数增加一次。打印：新行缩进。 
 * <p>（5）进行下一次循环。 
 * <p>3、如果当前字符是后方括号、后花括号做如下处理： 
 * <p>（1）后方括号、后花括号，的前面必须换行。打印：换行。 
 * <p>（2）每出现一次后方括号、后花括号；缩进次数减少一次。打印：缩进。 
 * <p>（3）打印：当前字符。 
 * <p>（4）如果当前字符后面还有字符，并且字符不为“，”，打印：换行。 
 * <p>（5）继续下一次循环。 
 * <p>4、如果当前字符是逗号。逗号后面换行，并缩进，不改变缩进次数。 
 * <p>5、打印：当前字符。 
 *  
 * @author  yanghaitao 
 * @version  [版本号, 2014年9月29日] 
 */
    public class JSONUtil
    {
        /** 
         * 单位缩进字符串。 
         */
        private static String SPACE = "   ";

        /** 
         * 返回格式化JSON字符串。 
         *  
         * @param json 未格式化的JSON字符串。 
         * @return 格式化的JSON字符串。 
         */
        public String formatJson(String json)
        {
            StringBuilder result = new StringBuilder();

            int length = json.Length;
            int number = 0;
            char key = ' ';

            //遍历输入字符串。  
            for (int i = 0; i < length; i++)
            {
                //1、获取当前字符。  
                key = json[i];

                //2、如果当前字符是前方括号、前花括号做如下处理：  
                if ((key == '[') || (key == '{'))
                {
                    //（1）如果前面还有字符，并且字符为“：”，打印：换行和缩进字符字符串。  
                    if ((i - 1 > 0) && (json[i - 1] == ':'))
                    {
                        result.Append('\n');
                        result.Append(indent(number));
                    }

                    //（2）打印：当前字符。  
                    result.Append(key);

                    //（3）前方括号、前花括号，的后面必须换行。打印：换行。  
                    result.Append('\n');

                    //（4）每出现一次前方括号、前花括号；缩进次数增加一次。打印：新行缩进。  
                    number++;
                    result.Append(indent(number));

                    //（5）进行下一次循环。  
                    continue;
                }

                //3、如果当前字符是后方括号、后花括号做如下处理：  
                if ((key == ']') || (key == '}'))
                {
                    //（1）后方括号、后花括号，的前面必须换行。打印：换行。  
                    result.Append('\n');

                    //（2）每出现一次后方括号、后花括号；缩进次数减少一次。打印：缩进。  
                    number--;
                    result.Append(indent(number));

                    //（3）打印：当前字符。  
                    result.Append(key);

                    //（4）如果当前字符后面还有字符，并且字符不为“，”，打印：换行。  
                    if (((i + 1) < length) && (json[i + 1] != ','))
                    {
                        result.Append('\n');
                    }

                    //（5）继续下一次循环。  
                    continue;
                }

                //4、如果当前字符是逗号。逗号后面换行，并缩进，不改变缩进次数。  
                if ((key == ','))
                {
                    result.Append(key);
                    result.Append('\n');
                    result.Append(indent(number));
                    continue;
                }

                //5、打印：当前字符。  
                result.Append(key);
            }

            return result.ToString();
        }

        /** 
         * 返回指定次数的缩进字符串。每一次缩进三个空格，即SPACE。 
         *  
         * @param number 缩进次数。 
         * @return 指定缩进次数的字符串。 
         */
        private String indent(int number)
        {
            StringBuilder result = new StringBuilder();
            for (int i = 0; i < number; i++)
            {
                result.Append(SPACE);
            }
            return result.ToString();
        }

        public static void main(String[] args)
        {
            JSONUtil tool = new JSONUtil();
            String toFormat = "{\"status\": \"3\",\"message\": \"\",\"errCode\": \"0\",\"data\": [{\"time\": \"2013-02-26 16:47\",\"context\": \"客户 同事收发家人 已签收 派件员 张xx\"},{\"time\": \"2013-02-26 07:33\",\"context\": \"吉林省xx市xx公司 的派件员 张金达 派件中 派件员电话15xxx73xx87\"},{\"time\": \"2013-02-26 06:02\",\"context\": \"xx省xx市xx公司 已收入\"},{\"time\": \"2013-02-25 15:42\",\"context\": \"xx省xx转运中心公司已发出\"},{\"time\":\"2013-02-25 14:59\",\"context\":\"xx省xx转运中心公司已拆包\"},{\"time\": \"2013-02-24 18:11\",\"context\":\"辽宁省大连市中山区四部公司 已收件\"},{\"time\": \"2013-02-24 17:59\",\"context\":\"辽宁省大连市公司 已收入\"},{\"time\":\"2013-02-23 17:10\",\"context\":\"辽宁省大连市中山区xxxx公司 的收件员 王xx 已收件\" }],\"html\":\"\",\"mailNo\":\"71xxxxx624\",\"expTextName\":\"圆通快递\",\"expSpellName\":\"yuantong\",\"update\":\"1375155719\",\"cache\":\"33196560\",\"ord\":\"DESC\"}";
            Console.WriteLine(tool.formatJson(toFormat));
        }
    }
}
